﻿using Payroll.Biz.Legacy.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Payroll.Biz.Legacy.Models
{
    public class HourlyClassification : IPaymentClassification
    {
        private static readonly double NORMAL_HOURS_PER_DAY = 8;

        private static readonly double OVERTIME_HOUR_RATE = 1.5;

        public decimal HourlyRate { get; private set; }

        public Dictionary<DateTime, TimeCard> TimeCards { get; private set; }

        public HourlyClassification(decimal hourlyRate)
        {
            HourlyRate = hourlyRate;
            TimeCards = new Dictionary<DateTime, TimeCard>();
        }

        public void AddTimeCard(TimeCard timeCard)
        {
            TimeCards.Add(timeCard.Date, timeCard);
        }

        public TimeCard GetTimeCard(DateTime date)
        {
            return TimeCards[date];
        }

        public decimal CalculatePay(Paycheck paycheck)
        {
            decimal result = 0;
            if ((TimeCards.Values == null) || (TimeCards.Values.Count == 0))
            {
                return result;
            }

#pragma warning disable S3267 // Loops should be simplified with "LINQ" expressions
            foreach (TimeCard timeCard in TimeCards.Values)
            {
                if (DateUtils.IsInPayPeriod(timeCard.Date, paycheck.PayPeriodStartDate, paycheck.PayPeriodEndDate))
                {
                    result += CalculatePayForTimeCard(timeCard);
                }
            }
#pragma warning restore S3267 // Loops should be simplified with "LINQ" expressions

            return result;
        }

        private decimal CalculatePayForTimeCard(TimeCard timeCard)
        {
            double overtimeHours = Math.Max(0, timeCard.Hours - NORMAL_HOURS_PER_DAY);
            double normalHours = timeCard.Hours - overtimeHours;

            return (HourlyRate * ((decimal)normalHours)) +
                (HourlyRate * ((decimal)OVERTIME_HOUR_RATE) * ((decimal)overtimeHours));
        }

        public override string ToString()
        {
            return $"{{{nameof(HourlyRate)}=${HourlyRate.ToString()}/hr, {nameof(TimeCards)}={TimeCards}}}";
        }

        public override bool Equals(object obj)
        {
            return (obj is HourlyClassification classification) && (HourlyRate == classification.HourlyRate);
        }

        public override int GetHashCode()
        {
            int hashCode = 1845455069;
            hashCode = (hashCode * (-1521134295)) + HourlyRate.GetHashCode();
            return hashCode;
        }
    }
}
